package cn.iocoder.yudao.module.promotion.redpacket.service.core;

import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.business.basic.dao.query.CoreLambdaQueryWrapper;
import cn.iocoder.yudao.framework.business.basic.service.impl.AbstractService;
import cn.iocoder.yudao.module.api.promotion.redpacket.enums.RedPacketContinueModeEnum;
import cn.iocoder.yudao.module.api.promotion.redpacket.enums.RedPacketGrantSceneEnum;
import cn.iocoder.yudao.module.api.promotion.redpacket.enums.RedPacketSourceEnum;
import cn.iocoder.yudao.module.api.promotion.redpacket.vo.RedPacketAmountVO;
import cn.iocoder.yudao.module.api.shop.info.ShopInfoApi;
import cn.iocoder.yudao.module.api.shop.info.dto.ShopInfoDTO;
import cn.iocoder.yudao.module.api.trade.order.dto.TradeOrderRespDTO;
import cn.iocoder.yudao.module.api.trade.scan.ScanOrderApi;
import cn.iocoder.yudao.module.api.trade.scan.dto.ScanOrderDTO;
import cn.iocoder.yudao.module.promotion.newcustomer.pojo.po.NewcustomerConfig;
import cn.iocoder.yudao.module.promotion.newcustomer.service.core.CoreNewcustomerConfigService;
import cn.iocoder.yudao.module.promotion.redpacket.convert.RedPacketRecordConvert;
import cn.iocoder.yudao.module.promotion.redpacket.dao.RedPacketConfigMapper;
import cn.iocoder.yudao.module.promotion.redpacket.dao.RedPacketRecordMapper;
import cn.iocoder.yudao.module.promotion.redpacket.dao.RedPacketUsedMapper;
import cn.iocoder.yudao.module.promotion.redpacket.mq.RedPacketProducer;
import cn.iocoder.yudao.module.promotion.redpacket.pojo.po.RedPacketConfig;
import cn.iocoder.yudao.module.promotion.redpacket.pojo.po.RedPacketRecord;
import cn.iocoder.yudao.module.promotion.redpacket.pojo.vo.RedPacketRecordVO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Nullable;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Objects;
import java.util.function.Function;

/**
 * <pre>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * 服务
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * </pre>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @since 2025/06/21
 */
@Slf4j
@Service
public class CoreRedPacketRecordService extends AbstractService<RedPacketRecord, RedPacketRecordVO> {
    @Resource
    private RedPacketConfigMapper redPacketConfigMapper;
    @Resource
    private RedPacketRecordMapper redPacketRecordMapper;
    @Resource
    private RedPacketUsedMapper redPacketUsedMapper;

    @Resource
    @Lazy // 延迟加载，避免循环依赖
    private CoreNewcustomerConfigService coreNewcustomerConfigService;

    @Resource
    @Lazy // 延迟加载，避免循环依赖
    private ShopInfoApi shopInfoApi;
    @Resource
    @Lazy // 延迟加载，避免循环依赖
    private ScanOrderApi scanOrderApi;

    @Resource
    private RedPacketProducer redPacketProducer;

    @Override
    public RedPacketRecordMapper getInjectedMapper() {
        return redPacketRecordMapper;
    }

    @Override
    public RedPacketRecordVO convertToViewObject(RedPacketRecord entity) {
        return RedPacketRecordConvert.INSTANCE.toViewObject(entity);
    }

    public boolean grantFirstOrderRedPacketIfNecessary(ScanOrderDTO order) {
        if (!StrUtil.contains(order.getNote(), "，使用首单优惠")) {
            log.warn("[grantFirstOrderRedPacketIfNecessary][订单({})不是首单优惠，忽略首单红包发放", order.getTradeNo());
            return false;
        }
        return grantFirstOrderRedPacketIfNecessary(order.getUserId(), order.getShopId(), order.getTradeNo());
    }

    private boolean grantFirstOrderRedPacketIfNecessary(Long userId, Long shopId, String tradeNo) {
        if (userId == null || userId <= 0) {
            log.warn("[grantFirstOrderRedPacketIfNecessary][用户为空] 订单疑似在未登录的情况下提交的，忽略首单红包发放");
            return false;
        }
        String shopName;
        try {
            ShopInfoDTO shopInfo = shopInfoApi.validShopInfo(shopId);
            shopName = shopInfo.getName();
        } catch (Exception e) {
            log.warn("[grantFirstOrderRedPacketIfNecessary][店铺({}) 信息校验异常:{}] 忽略首单红包发放", shopId, e.getMessage());
            return false;
        }
        NewcustomerConfig config = coreNewcustomerConfigService.getOrCreate(shopId);
        if (config == null || !Boolean.TRUE.equals(config.getEnabled())) {
            log.debug("[grantFirstOrderRedPacketIfNecessary][店铺({}) 的新客优惠功能未开启] 忽略首单红包发放", shopId);
            return false;
        }
        if (config.getRewardType() != 1) {
            log.debug("[grantFirstOrderRedPacketIfNecessary][店铺({}) 的新客优惠奖励类型不是红包] 忽略首单红包发放", shopId);
            return false;
        }
        if (config.getRedPacketAmount() <= 0) {
            log.debug("[grantFirstOrderRedPacketIfNecessary][店铺({}) 的新客优惠奖励红包金额设置无效] 忽略首单红包发放", shopId);
            return false;
        }
        CoreLambdaQueryWrapper<RedPacketRecord> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.eq(RedPacketRecord::getFromTradeNo, tradeNo);
        RedPacketRecord redPacketRecord = redPacketRecordMapper.selectOne(wrapper);
        if (redPacketRecord != null) {
            log.debug("[grantFirstOrderRedPacketIfNecessary][用户({})在店铺({})已发放过首单红包] 忽略首单红包发放", userId, shopId);
            return false;
        }
        RedPacketRecord record = new RedPacketRecord();
        record.setUserId(userId);
        record.setShopId(shopId);
        record.setSource(RedPacketSourceEnum.NEW_CUSTOMER_AFTER.getValue());
        record.setFromTradeNo(tradeNo);
        record.setAmount(config.getRedPacketAmount());
        record.setGrantedTime(LocalDateTime.now());
        record.setEffectTime(LocalDateTime.now().plusHours(12));
        record.setExpiredTime(LocalDateTime.now().plusDays(7));
        record.setRemark("订单【" + tradeNo + "】完成，商家【" + shopName + "】发放首单红包");
        if (redPacketRecordMapper.insert(record) > 0) {
            redPacketProducer.sendRedPacketGrantMessage(shopId, userId, record.getAmount(), record.getId(), record.getRemark());
            return true;
        }
        return false;
    }

    @Nullable
    public RedPacketRecord grantNewCustomerRedPacketIfNecessary(Long userId, Long shopId) {
        if (userId == null || userId <= 0) {
            log.warn("[grantNewCustomerRedPacketIfNecessary][用户为空] 订单疑似在未登录的情况下提交的，忽略消费红包发放");
            return null;
        }
        String shopName;
        try {
            ShopInfoDTO shopInfo = shopInfoApi.validShopInfo(shopId);
            shopName = shopInfo.getName();
        } catch (Exception e) {
            log.warn("[grantNewCustomerRedPacketIfNecessary][店铺({})信息校验异常:{}] 忽略新客红包发放", shopId, e.getMessage());
            return null;
        }
        try {
            if (!scanOrderApi.isNewShopCustomer(shopId, userId)) {
                log.debug("[grantNewCustomerRedPacketIfNecessary][用户({})非店铺({})新客] 忽略新客红包发放", userId, shopId);
                return null;
            }
            RedPacketConfig config = redPacketConfigMapper.selectByShopId(shopId);
            if (config == null || !Boolean.TRUE.equals(config.getFeatureEnable())) {
                log.debug("[grantNewCustomerRedPacketIfNecessary][店铺({})的红包功能未开启] 忽略新客红包发放", shopId);
                return null;
            }
            if (config.getFirstAmount() <= 0) {
                log.debug("[grantNewCustomerRedPacketIfNecessary][店铺({})的新客红包金额小于等于0] 忽略新客红包发放", shopId);
                return null;
            }
            if (redPacketRecordMapper.existsNewCustomerRedPacket(userId, shopId)) {
                log.debug("[grantNewCustomerRedPacketIfNecessary][用户({})在店铺({})已发放过新客红包] 忽略新客红包发放", userId, shopId);
                return null;
            }
            RedPacketRecord record = new RedPacketRecord();
            record.setUserId(userId);
            record.setShopId(shopId);
            record.setSource(RedPacketSourceEnum.NEW_CUSTOMER_BEFORE.getValue());
            record.setFromTradeNo("");
            record.setAmount(config.getFirstAmount());
            record.setGrantedTime(LocalDateTime.now());
            record.setEffectTime(LocalDateTime.now());
            record.setExpiredTime(LocalDateTime.now().plusDays(config.getValidationDays()));
            record.setRemark("商家【" + shopName + "】发放新客红包");
            redPacketRecordMapper.insert(record);
            redPacketProducer.sendRedPacketGrantMessage(shopId, userId, record.getAmount(), record.getId(), record.getRemark());
            return record;
        } catch (Exception e) {
            log.warn("[grantNewCustomerRedPacketIfNecessary][用户({})在店铺({})发放新客红包异常:{}] 忽略新客红包发放", userId, shopId, e.getMessage());
            return null;
        }
    }

    public void grantEveryConsumeRedPacketIfNecessary(ScanOrderDTO order) {
        grantEveryConsumeRedPacketIfNecessary(order.getUserId(), order.getShopId(), order.getTradeNo(), o -> validPayPrice(order, o));
    }

    public void grantEveryConsumeRedPacketIfNecessary(TradeOrderRespDTO order) {
        grantEveryConsumeRedPacketIfNecessary(order.getUserId(), order.getShopId(), order.getNo(), o -> validPayPrice(order, o));
    }

    public void grantEveryConsumeRedPacketIfNecessary(Long userId, Long shopId, String tradeNo, Function<RedPacketConfig, Integer> validPayPrice) {
        if (userId == null || userId <= 0) {
            log.warn("[grantEveryConsumeRedPacketIfNecessary][用户为空] 订单疑似在未登录的情况下提交的，忽略消费红包发放");
            return;
        }
        String shopName;
        try {
            ShopInfoDTO shopInfo = shopInfoApi.validShopInfo(shopId);
            shopName = shopInfo.getName();
        } catch (Exception e) {
            log.warn("[grantEveryConsumeRedPacketIfNecessary][店铺({}) 信息校验异常:{}] 忽略消费红包发放", shopId, e.getMessage());
            return;
        }
        RedPacketConfig config = redPacketConfigMapper.selectByShopId(shopId);
        if (config == null || !Boolean.TRUE.equals(config.getFeatureEnable())) {
            log.debug("[grantEveryConsumeRedPacketIfNecessary][店铺({}) 的红包功能未开启] 忽略消费红包发放", shopId);
            return;
        }
        LocalTime now = LocalTime.now();
        if (now.isBefore(config.getContinueGrantStartTime())) {
            log.debug("[grantEveryConsumeRedPacketIfNecessary][店铺({})的消费红包发放时间未开始] 忽略消费红包发放", shopId);
            return;
        }
        if (now.isAfter(config.getContinueGrantEndTime())) {
            log.debug("[grantEveryConsumeRedPacketIfNecessary][店铺({})的消费红包发放时间已结束] 忽略消费红包发放", shopId);
            return;
        }
        if (Objects.equals(config.getContinueMode(), RedPacketContinueModeEnum.FIXED.getValue())
            && config.getContinueAmount() <= 0) {
            log.debug("[grantEveryConsumeRedPacketIfNecessary][店铺({})的消费红包使用固定金额发放模式，但是配置的固定金额小于等于0] 忽略消费红包发放", shopId);
            return;
        }
        int payPrice = validPayPrice.apply(config);
        if (payPrice <= 0) {
            log.debug("[grantEveryConsumeRedPacketIfNecessary][用户({})在店铺({})下单({})消费未满足发放条件] 忽略消费红包发放", userId, shopId, tradeNo);
            return;
        }
        CoreLambdaQueryWrapper<RedPacketRecord> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.eq(RedPacketRecord::getFromTradeNo, tradeNo);
        RedPacketRecord redPacketRecord = redPacketRecordMapper.selectOne(wrapper);
        if (redPacketRecord != null) {
            log.debug("[grantEveryConsumeRedPacketIfNecessary][用户({})在店铺({})已发放过消费红包] 忽略消费红包发放", userId, shopId);
            return;
        }
        RedPacketRecord record = new RedPacketRecord();
        record.setUserId(userId);
        record.setShopId(shopId);
        record.setSource(RedPacketSourceEnum.EVERY_CONSUME.getValue());
        record.setFromTradeNo(tradeNo);
        record.setAmount(Objects.equals(config.getContinueMode(), RedPacketContinueModeEnum.FIXED.getValue()) ?
                config.getContinueAmount() : payPrice);
        record.setGrantedTime(LocalDateTime.now());
        record.setEffectTime(LocalDateTime.now().plusHours(config.getDelayEffectHours()));
        record.setExpiredTime(LocalDateTime.now().plusDays(config.getValidationDays()));
        record.setRemark("订单【" + tradeNo + "】完成，商家【" + shopName + "】发放消费红包");
        if (redPacketRecordMapper.insert(record) > 0) {
            redPacketProducer.sendRedPacketGrantMessage(shopId, userId, record.getAmount(), record.getId(), record.getRemark());
        }
    }

    private int validPayPrice(ScanOrderDTO order, RedPacketConfig config) {
        int payPrice = 0;
        if (Objects.equals(config.getContinueGrantScene(), RedPacketGrantSceneEnum.ALL.getValue()) ||
            Objects.equals(config.getContinueGrantScene(), RedPacketGrantSceneEnum.SCAN_ORDER.getValue())) {
            if (!Objects.equals(order.getPrice(), order.getOriginPrice())) {
                log.debug("[validPayPrice][用户({})在店铺({})下单({})扫码付款不是原价] 忽略消费红包发放", order.getUserId(), order.getShopId(), order.getTradeNo());
            } else if (order.getPrice() < config.getContinueThresholdPrice()) {
                log.debug("[validPayPrice][用户({})在店铺({})下单({})扫码付款未到达发放门槛金额({})] 忽略消费红包发放", order.getUserId(), order.getShopId(), order.getTradeNo(), config.getContinueThresholdPrice());
            } else {
                payPrice = order.getPrice();
            }
        } else {
            log.debug("[validPayPrice][用户({})在店铺({})下单({})不支持扫码付款(设置的场景是#{})下发放红包] 忽略消费红包发放", order.getUserId(), order.getShopId(), order.getTradeNo(), config.getContinueGrantScene());
        }
        return payPrice;
    }

    private int validPayPrice(TradeOrderRespDTO order, RedPacketConfig config) {
        int payPrice = 0;
        if (Objects.equals(config.getContinueGrantScene(), RedPacketGrantSceneEnum.ALL.getValue()) ||
            Objects.equals(config.getContinueGrantScene(), RedPacketGrantSceneEnum.TRADE_ORDER.getValue())) {
            if (!Objects.equals(order.getPayPrice(), order.getTotalPrice())) {
                log.debug("[validPayPrice][用户({})在店铺({})下单({})商城购物不是原价] 忽略消费红包发放", order.getUserId(), order.getShopId(), order.getNo());
            } else if (order.getPayPrice() < config.getContinueThresholdPrice()) {
                log.debug("[validPayPrice][用户({})在店铺({})下单({})商城购物未到达发放门槛金额({})] 忽略消费红包发放", order.getUserId(), order.getShopId(), order.getNo(), config.getContinueThresholdPrice());
            } else {
                payPrice = order.getPayPrice();
            }
        } else {
            log.debug("[validPayPrice][用户({})在店铺({})下单({})不支持商城购物(设置的场景是#{})下发放红包] 忽略消费红包发放", order.getUserId(), order.getShopId(), order.getNo(), config.getContinueGrantScene());
        }
        return payPrice;
    }

    public RedPacketAmountVO getRedPacketAmount(Long userId, Long shopId) {
        int totalAmount = redPacketRecordMapper.sumTotalAmount(userId, shopId);
        int usedAmount = redPacketUsedMapper.sumUsedAmount(userId, shopId);
        int uneffectedAmount = redPacketRecordMapper.sumUneffectedAmount(userId, shopId);
        int remainingAmount = totalAmount - usedAmount - uneffectedAmount;
        int expiredAndUsedAmount = redPacketRecordMapper.sumExpiredAndUsedAmount(userId, shopId);
        int expiredAmount = remainingAmount <= expiredAndUsedAmount ? remainingAmount : remainingAmount - expiredAndUsedAmount;
        int unusedAmount = totalAmount - usedAmount - uneffectedAmount - expiredAmount;
        log.debug("用户[{}]在店铺[{}]下的红包汇总：totalAmount={}, usedAmount={}, uneffectedAmount={}, remainingAmount={}, unusedAmount={}, expiredAndUsedAmount={}, expiredAmount={}", userId, shopId, totalAmount, usedAmount, uneffectedAmount, remainingAmount, unusedAmount, expiredAndUsedAmount, expiredAmount);
        RedPacketAmountVO amount = new RedPacketAmountVO();
        amount.setTotalAmount(totalAmount);
        amount.setUsedAmount(usedAmount);
        amount.setExpiredAmount(expiredAmount);
        amount.setUnusedAmount(unusedAmount);
        amount.setUneffectedAmount(uneffectedAmount);
        return amount;
    }

}
